using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.Diagnostics;

namespace Mpi.Common.Controls
{
    public partial class TimeSpanBox : UserControl
    {
        private int activeBox;
        private float xSize;
        private float ySize;
        private float xSizeDays;
        private float ySizeDays;
        private RectangleF[] rec;
        private RectangleF[] brec;
        private int[] number;
        //private Font font;

        private bool _drawInfoLabel;

        public bool DrawInfoLabel
        {
            get { return _drawInfoLabel; }
            set { _drawInfoLabel = value; CalculateBoxSize(); }
        }


        private Font _labelFont;
        public Font LabelFont
        {
            get { return _labelFont; }
            set
            {
                _labelFont = value;
                this.CalculateBoxSize();
                this.Invalidate();
                int x = 0;
                

            }
        }

        public new Font Font
        {
            get { return base.Font; }
            set
            {
                base.Font = value;
                this.CalculateBoxSize();
                this.Invalidate();
            }
        }

        public TimeSpanBox()
        {
            activeBox = 0;

            rec = new RectangleF[4];
            brec = new RectangleF[3];
            number = new int[4];

            number[0] = 000;
            number[1] = 00;
            number[2] = 00;
            number[3] = 00;

            base.Font = new Font("Arial", 10f);
            _labelFont = new Font("Arial", 9);
            InitializeComponent();

            this.CalculateBoxSize();
        }

        private void CheckNumbers()
        {
            /*if (number[0] > 99)
                           {
                               number[0] = Convert.ToInt32("0" + number[1].ToString("00").Substring(1, 1));
                           }*/



            if (number[1] > 23)
            {
                number[1] = Convert.ToInt32("0" + number[1].ToString("00").Substring(1, 1));
            }
            if (number[2] > 59)
            {
                number[2] = Convert.ToInt32("0" + number[1].ToString("00").Substring(1, 1));
            }
            if (number[3] > 59)
            {
                number[3] = Convert.ToInt32("0" + number[1].ToString("00").Substring(1, 1));
            }

        }

        private void CkeckMinMax()
        {
            TimeSpan v = this.Value;
            if (_min > v)
            {
                number[0] = _min.Days;
                number[1] = _min.Hours;
                number[2] = _min.Minutes;
                number[3] = _min.Seconds;
            }
            if (_max < v)
            {
                number[0] = _max.Days;
                number[1] = _max.Hours;
                number[2] = _max.Minutes;
                number[3] = _max.Seconds;
            }
        }

        private void DrawNumbers(PaintEventArgs pea)
        {

            for (int i = 1; i <= 4; i++)
            {
                if (activeBox == i)
                {
                    if (i == 1)
                        pea.Graphics.DrawString(number[i - 1].ToString("0000"), this.Font, System.Drawing.SystemBrushes.HighlightText, rec[i - 1].Left, rec[i - 1].Top);
                    else
                        pea.Graphics.DrawString(number[i - 1].ToString("00"), this.Font, System.Drawing.SystemBrushes.HighlightText, rec[i - 1].Left, rec[i - 1].Top);
                }
                else
                {
                    if (i == 1)
                        pea.Graphics.DrawString(number[i - 1].ToString("0000"), this.Font, System.Drawing.SystemBrushes.WindowText, rec[i - 1].Left, rec[i - 1].Top);
                    else
                        pea.Graphics.DrawString(number[i - 1].ToString("00"), this.Font, System.Drawing.SystemBrushes.WindowText, rec[i - 1].Left, rec[i - 1].Top);
                }
            }

            pea.Graphics.DrawString(".", this.Font, System.Drawing.SystemBrushes.WindowText, rec[0].Right - 3, rec[0].Top); // HIER...
            pea.Graphics.DrawString(":", this.Font, System.Drawing.SystemBrushes.WindowText, rec[1].Right - 3, rec[1].Top);
            pea.Graphics.DrawString(":", this.Font, System.Drawing.SystemBrushes.WindowText, rec[2].Right - 3, rec[2].Top);

            if (DrawInfoLabel)
            {
                pea.Graphics.DrawString("dddd.hh:mm:ss", this.LabelFont, Brushes.Silver, rec[0].Left, rec[0].Bottom - 1);
            }
        }

        private void DrawRecs(PaintEventArgs pea)
        {
            for (int i = 1; i <= 4; i++)
            {
                if (activeBox == i)
                {
                    pea.Graphics.FillRectangle(System.Drawing.SystemBrushes.Highlight, rec[i - 1]);
                }
                //				else
                //				{
                //					pea.Graphics.FillRectangle(System.Drawing.SystemBrushes.Window, rec[i - 1]);
                //				}
            }
        }

        private void AddOneToBox(int box)
        {
            if (box == 1)
            {
                if (number[box - 1] < 9999)
                {
                    number[box - 1]++;
                    this.Refresh();
                }
            }
            else if (box == 2)
            {
                if (number[box - 1] < 23)
                {
                    number[box - 1]++;
                }
                else
                {
                    number[box - 1] = 00;
                    AddOneToBox(box - 1);
                    //number[activeBox - 2]++;
                }
                this.Refresh();
            }
            else if (box == 3)
            {
                if (number[box - 1] < 59)
                {
                    number[box - 1]++;
                }
                else
                {
                    number[box - 1] = 00;
                    AddOneToBox(box - 1);
                    //number[activeBox - 2]++;
                }
                this.Refresh();
            }
            else if (box == 4)
            {
                if (number[box - 1] < 59)
                {
                    number[box - 1]++;
                }
                else
                {
                    number[box - 1] = 00;
                    AddOneToBox(box - 1);
                }
                this.Refresh();
            }
        }


        private void SubOneFromBox(int box)
        {
            if (box == 1)
            {
                if (number[box - 1] > 0000)
                {
                    number[box - 1]--;
                    this.Refresh();
                }
            }
            else if (box == 2)
            {
                if (number[box - 1] > 00)
                {
                    number[box - 1]--;
                }
                else
                {
                    number[box - 1] = 23;
                    SubOneFromBox(box - 1);

                }
                this.Refresh();
            }
            else if (box == 3)
            {
                if (number[box - 1] > 00)
                {
                    number[box - 1]--;
                }
                else
                {
                    number[box - 1] = 59;
                    SubOneFromBox(box - 1);
                }
                this.Refresh();
            }
            else if (box == 4)
            {
                if (number[box - 1] > 00)
                {
                    number[box - 1]--;
                }
                else
                {
                    number[box - 1] = 59;
                    SubOneFromBox(box - 1);
                }
                this.Refresh();
            }
        }

        // --- Override --->
        // Focus ---->
        protected override void OnGotFocus(EventArgs e)
        {
            base.OnGotFocus(e);
            activeBox = 1;
            this.Refresh();
        }

        protected override void OnLostFocus(EventArgs e)
        {
            base.OnLostFocus(e);
            activeBox = 0;
            this.Refresh();
        }

        // Key + Mouse input ---->
        protected override void OnKeyUp(KeyEventArgs e)
        {
            base.OnKeyUp(e);
            if (e.KeyValue == Convert.ToInt32(Keys.Left))
            {
                if (activeBox > 1)
                {
                    activeBox--;
                    this.Refresh();
                }
                else if (activeBox == 1)
                {
                    activeBox = 4;
                    this.Refresh();
                }
            }
            else if (e.KeyValue == Convert.ToInt32(Keys.Right))
            {
                if (activeBox < 4)
                {
                    activeBox++;
                    this.Refresh();
                }
                else if (activeBox == 4)
                {
                    activeBox = 1;
                    this.Refresh();
                }

            }
            else if (e.KeyValue == Convert.ToInt32(Keys.Up))
            {
                AddOneToBox(activeBox);
                CkeckMinMax();
                this.Refresh();
                this.OnValueChanged();
            }
            else if (e.KeyValue == Convert.ToInt32(Keys.Down))
            {
                SubOneFromBox(activeBox);
                CkeckMinMax();
                this.Refresh();
                this.OnValueChanged();
                //if (number[activeBox - 1] > 00)
                //{
                //    number[activeBox - 1]--;
                //    this.Refresh();
                //    this.OnValueChanged();
                //}
            }
        }

        protected override bool IsInputKey(Keys keyData)
        {
            base.IsInputKey(keyData);
            if (keyData == Keys.Up || keyData == Keys.Down || keyData == Keys.Left || keyData == Keys.Right)
            {
                return true;
            }
            else
            {
                return base.IsInputKey(keyData);
            }
        }

        /*
                       protected override bool ProcessDialogKey(Keys keyData)
                       {
                          return base.ProcessDialogKey(keyData);
                       } 
                       */

        protected override void OnKeyDown(KeyEventArgs e)
        {

            base.OnKeyDown(e);
            if (activeBox > 0)
            {
                Keys key = e.KeyData;
                if (Keys.D0 == key || Keys.D1 == key || Keys.D2 == key || Keys.D3 == key ||
                    Keys.D4 == key || Keys.D5 == key || Keys.D6 == key || Keys.D7 == key ||
                    Keys.D8 == key || Keys.D9 == key)
                {
                    if (activeBox > 1)
                        number[activeBox - 1] = Convert.ToInt32(number[activeBox - 1].ToString("00").Substring(1, 1) +
                            Convert.ToInt32(key.ToString().Substring(1, 1)).ToString());
                    else
                        number[activeBox - 1] = Convert.ToInt32(number[activeBox - 1].ToString("0000").Substring(1, 3) +
                        Convert.ToInt32(key.ToString().Substring(1, 1)).ToString());
                    CkeckMinMax();
                    this.Refresh();
                    this.OnValueChanged();

                }
                else if (Keys.NumPad0 == key || Keys.NumPad1 == key || Keys.NumPad2 == key ||
                    Keys.NumPad3 == key || Keys.NumPad4 == key || Keys.NumPad5 == key ||
                    Keys.NumPad6 == key || Keys.NumPad7 == key || Keys.NumPad8 == key ||
                    Keys.NumPad9 == key)
                {
                    if (activeBox > 1)
                        number[activeBox - 1] = Convert.ToInt32(number[activeBox - 1].ToString("00").Substring(1, 1) +
                            Convert.ToInt32(key.ToString().Substring(6, 1)).ToString());
                    else
                        number[activeBox - 1] = Convert.ToInt32(number[activeBox - 1].ToString("0000").Substring(1, 3) +
                        Convert.ToInt32(key.ToString().Substring(6, 1)).ToString());

                    //number[activeBox - 1] = Convert.ToInt32(number[activeBox - 1].ToString("00").Substring(1, 1) +
                    //    Convert.ToInt32(key.ToString().Substring(6, 1)).ToString());
                    CkeckMinMax();
                    this.Refresh();
                    this.OnValueChanged();
                }
                else if (key == Keys.Delete)
                {
                    number[activeBox - 1] = 00;
                    this.Refresh();
                    this.OnValueChanged();
                }
                else if (key == Keys.Back)
                {
                    number[activeBox - 1] = 00;
                    if (activeBox > 1)
                    {
                        activeBox--;
                    }
                    this.Refresh();
                    this.OnValueChanged();
                }
            }
        }

        protected override void OnMouseWheel(MouseEventArgs e)
        {
            base.OnMouseWheel(e);
            if (e.Delta >= 120)
            {
                AddOneToBox(activeBox);
                CkeckMinMax();
                this.Refresh();
                this.OnValueChanged();
            }
            else if (e.Delta <= -120)
            {
                SubOneFromBox(activeBox);
                CkeckMinMax();
                this.Refresh();
                this.OnValueChanged();
                //if (number[activeBox - 1] > 00)
                //{
                //    number[activeBox - 1]--;
                //    this.Refresh();
                //    this.OnValueChanged();
                //}
            }
        }

        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);
            if (e.X > 2 && e.X < (2 + xSizeDays))
            {
                activeBox = 1;
                this.Refresh();
            }
            else if (e.X > (2 + xSizeDays + brec[0].Width) && e.X < (2 + xSizeDays + xSize + brec[0].Width))
            {
                activeBox = 2;
                this.Refresh();
            }
            else if (e.X > (2 + xSizeDays + xSize + brec[0].Width + brec[1].Width) && e.X < (2 + xSizeDays + (xSize * 2) + brec[0].Width + brec[1].Width))
            {
                activeBox = 3;
                this.Refresh();
            }
            else if (e.X > (2 + xSizeDays + (xSize * 2) + brec[0].Width + brec[1].Width + brec[2].Width) && e.X < (2 + xSizeDays + (xSize * 3) + brec[0].Width + brec[1].Width + brec[2].Width))
            {
                activeBox = 4;
                this.Refresh();
            }
        }

        private void InitializeComponent()
        {
            this.SuspendLayout();
            // 
            // TimeSpanPicker
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            


            this.DoubleBuffered = true;
            this.Name = "TimeSpanPicker";
            this.Size = new System.Drawing.Size(201, 30);
            this.SizeChanged += new System.EventHandler(this.TimeSpanPicker_SizeChanged);
            this.ResumeLayout(false);

        }

        private void CalculateBoxSize()
        {

            if (this.Font != null)
            {
                Graphics g = this.CreateGraphics();
                SizeF s = g.MeasureString("00", this.Font);
                SizeF s2 = g.MeasureString("dddd:hh:mm:ss", _labelFont);

                if (DrawInfoLabel)
                    this.Height = (int)Math.Ceiling(s.Height + s2.Height) + 1;
                else
                    this.Height = (int)Math.Ceiling(s.Height) + 2;

                s = g.MeasureString("0000.00:00:00", this.Font);
                this.Width = (int)Math.Ceiling(s.Width);
                this.MinimumSize = new Size(this.Width, 0);
                //this.MaximumSize = new Size(this.Width, 0);
                g.Dispose();
                g = null;

            }

            //	this.Height = (int) (ySize + 5);

        }

        public new Size Size
        {
            get
            {
                return base.Size;
            }
            set
            {
                this.Invalidate();
            }
        }

        // Paint ---->
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            //			xSize = (Width - 1)/5 ;
            //			ySize = (Height - 1) - 3;

            //float separtorBoxWidth = 2;

            if (this.Font != null)
            {
                SizeF s = e.Graphics.MeasureString("00", this.Font);
                this.xSize = (float)Math.Floor(s.Width - 2);
                this.ySize = (float)Math.Round(s.Height - 2);
                SizeF sDays = e.Graphics.MeasureString("0000", this.Font);
                this.xSizeDays = (float)Math.Floor(sDays.Width - 2);
                //this.ySizeDays = (float)Math.Round(sDays.Height - 2);

            }
            else
            {
                xSize = (Width - 1) / 5;
                ySize = (Height - 1) - 3;
            }

            rec[0] = new RectangleF(2, 2, xSizeDays, ySize);
            rec[1] = new RectangleF(rec[0].Right + 1, 2, xSize, ySize);
            rec[2] = new RectangleF(rec[1].Right + 1, 2, xSize, ySize);
            rec[3] = new RectangleF(rec[2].Right + 1, 2, xSize, ySize);

            brec[0] = new RectangleF(rec[0].X + rec[0].Width, 2, 2, ySize);
            brec[1] = new RectangleF(rec[1].X + rec[1].Width, 2, 2, ySize);
            brec[2] = new RectangleF(rec[2].X + rec[2].Width, 2, 2, ySize);

            CheckNumbers();
            e.Graphics.FillRectangle(SystemBrushes.Window, 0, 0, Width - 1, Height - 1);
            e.Graphics.DrawRectangle(Pens.Gray, 0, 0, Width - 1, Height - 1);// HIER...
            DrawRecs(e);
            DrawNumbers(e);
        }

        private void TimeSpanPicker_SizeChanged(object sender, System.EventArgs e)
        {
            //this.Refresh();
            this.Invalidate();
        }

        private TimeSpan oldValue;
        private TimeSpan _min;

        public TimeSpan Min
        {
            get { return _min; }
            set
            {
                if (this.Value < value)
                {
                    Value = value;

                }
                _min = value;
            }
        }
        private TimeSpan _max = TimeSpan.MaxValue;

        public TimeSpan Max
        {
            get { return _max; }
            set
            {
                if (this.Value > value)
                {
                    Value = value;

                }
                _max = value;
            }
        }
        // ----- Public ----->
        public TimeSpan Value
        {
            get { return IntArrayToTimeSpan(); }
            set
            {
                TimeSpan toSet = value;
                if (value < _min)
                {
                    toSet = _min;

                }
                if (value > _max)
                {
                    toSet = _max;

                }
                if (this.Value != toSet)
                {
                    number[0] = toSet.Days;
                    number[1] = toSet.Hours;
                    number[2] = toSet.Minutes;
                    number[3] = toSet.Seconds;
                    this.OnValueChanged();
                    this.oldValue = value;
                    this.Refresh();
                }
            }
        }

        private TimeSpan IntArrayToTimeSpan()
        {
            return new TimeSpan(number[0], number[1], number[2], number[3]);
        }

        public delegate void ValueChangedEventHandler(object sender);
        public event EventHandler ValueChanged;

        protected virtual void OnValueChanged()
        {
            if (this.Value != oldValue)
            {
                if (ValueChanged != null)
                    ValueChanged(this, new EventArgs());
                this.oldValue = this.Value;
            }
        }

        public string ReadableValue
        {
            get
            {
                return TimeSpanExtension.ReadableValueDuration(this.Value);
                //ArrayList strings = new ArrayList();

                //if (this.Value.Days % 7 == 0)
                //{
                //    int weeks = this.Value.Days / 7;


                //    if (weeks == 1)
                //    {
                //        strings.Add(weeks + " week");
                //    }
                //    if (weeks > 1)
                //    {
                //        strings.Add(weeks + " weeks");
                //    }
                //}
                //else
                //{
                //    if (this.Value.Days == 1)
                //    {
                //        strings.Add(this.Value.Days + " day");
                //    }
                //    else if (this.Value.Days > 1)
                //    {
                //        strings.Add(this.Value.Days + " days");
                //    }
                //}

                ////if(this.Value.Days >= 7)
                ////{
                ////    int weeks = this.Value.Days / 7;


                ////    if (weeks == 1)
                ////    {
                ////        strings.Add(weeks + " week");
                ////    }
                ////    if (weeks > 1)
                ////    {
                ////        strings.Add(weeks + " weeks");
                ////    }


                ////    int days = this.Value.Days / 7;
                ////    if (days == 1)
                ////    {
                ////        strings.Add(days + " day");
                ////    }
                ////    if (days > 1)
                ////    {
                ////        strings.Add(days + " days");
                ////    }
                ////}
                ////else if (this.Value.Days == 1)
                ////{
                ////    strings.Add(this.Value.Days + " day");
                ////}else if(this.Value.Days >1)
                ////{
                ////    strings.Add(this.Value.Days + " days");
                ////}

                //if (this.Value.Hours == 1)
                //    strings.Add(this.Value.Hours + " hour");
                //if (this.Value.Hours > 1)
                //    strings.Add(this.Value.Hours + " hours");
                //if (this.Value.Minutes == 1)
                //    strings.Add(this.Value.Minutes + " minute");
                //if (this.Value.Minutes > 1)
                //    strings.Add(this.Value.Minutes + " minutes");
                //if (this.Value.Seconds == 1)
                //    strings.Add(this.Value.Seconds + " second");
                //if (this.Value.Seconds > 1)
                //    strings.Add(this.Value.Seconds + " seconds");
                //string r = "";
                //for (int i = 0; i < strings.Count; i++)
                //{
                //    r += strings[i];
                //    if (i < strings.Count - 1)
                //    {

                //        r += ", ";
                //    }
                //    //else
                //    //{
                //    //    if(r.Length > 2)
                //    //    {
                //    //        r.Remove(r.Length-2,2);
                //    //        r += " and ";
                //    //    }
                //    //    r +=  strings[i];
                //    //}
                //}
                //if (r.Length == 0)
                //    r = "Zero";
                //return r;

            }
        }

        public string ReadableValue2
        {
            get
            {
                return TimeSpanExtension.ReadableValuePoint(this.Value);
                //ArrayList strings = new ArrayList();

                ////if (this.Value.Days > 0 && this.Value.Days % 7 == 0)
                ////{
                ////    int weeks = this.Value.Days / 7;

                ////    strings.Add("week " + weeks);
                ////}
                ////else 
                //if (this.Value.Days > 0)
                //{
                //    strings.Add("day " + this.Value.Days);
                //}


                //if (this.Value.Hours > 0)
                //    strings.Add("hour " + this.Value.Hours);

                //if (this.Value.Minutes > 0)
                //    strings.Add("minute " + this.Value.Minutes);
                //if (this.Value.Seconds > 0)
                //    strings.Add("second " + this.Value.Seconds);
                //string r = "";
                //for (int i = 0; i < strings.Count; i++)
                //{
                //    r += strings[i];
                //    if (i < strings.Count - 1)
                //    {

                //        r += ", ";
                //    }
                //}
                //if (r.Length == 0)
                //    r = "Zero";
                //return r;

            }
        }
    }
}
